Node.js Buffer

Buffer

缓冲区是内存区域,和直接与内存交互的编程语言 C、C++、Go 等相比,JavaScript 对这个操作很微乎其微,因此为了实现与内存区域打交道,Buffer 由此而生。

Buffer class

Buffer 类主要的作用就是一个专门用于存放二进制数据的缓存区,是 Node 专门定义的一个类,用于弥补 JavaScript 自由的字符串类型无法满足大量二进制数据处理。

Buffer 是 Node 的一个核心库,因此为 Node 带来了另一种原始的数据存储方法(二进制),让 Node 处理 二进制数据。

所以 Buffer 库主要的用处就是需要 Node 处理 I/O 的时候,就可以通过 Buffer 库进行一个处理,当然也可以进行字符编码或数据类型的转换。

缓冲区可以通过使用 Buffer.[form(),alloc(),allocUnsafe()] 方法进行构建,这也涉及到了 Buffer 方法:

Id Name Info Type
1 buffer.alloc 可以创建任意大小的缓存区 type
2 buffer.from(arrayBuffer[, byteOffset[, length]) 能够通过字符串、缓冲区、数组等方式创建缓存区 type
byteOffset 需要暴露的地一个索引值
length 暴露的字节数
0x1 buffer.byteLength() 查询字节长度 method
0x2 buffer.compare(target[,target1,target..]) 比较两个缓冲区(buffer)对象是否相等,并返回 -1、0、1 method
0 与 target 相等返回 0
1 如果 target 的 size 不同以及 fill 相等,则返回 1
-1 如果 target 的 fill 不相等,则返回 -1
0x3 buffer.concat 将一个或多个缓存区对象合并为一个对象,合并后可以获取新的对象长度 method
0x4 buffer.entries() 用于返回缓冲区的 [index,byte] method
0x5 buffer.fill() 用于缓冲区填充 method
0x6 buffer.includes(values) 用于判断 values 是否在缓冲区(buffer)中 method
0x7 buffer.isEncoding 判断 Buffer 目前所支持的编码名称 method
0x8 buf.slice(start[,end]) 用于将 buffe 内的 fill 进行切片 method
0x9 buf.toJSON() 将数据输出为 JSON 格式 method
0x10 buf.write(string[,offset,length,encoding]) 将 string 写入 buffer 中 method

buffer.alloc

1
2
3
4
5
6
7
8
9
10
const buf = Buffer.alloc(10, 1)

// <Buffer 01 01 01 01 01 01 01 01 01 01>
console.log(buf)

// 返回字节的长度
var buflen = Buffer.byteLength(buf)

// 10
console.log(buflen)

创建一个大小为 10 的缓存区,且用 1 进行填充,并通过 Buffer.byteLength 来查询字节的长度。

length 的区别是 byteLength 不会考虑用于将字符串转换为字节编码

buffer.fill(arrayBuffer[, byteOffset[, length])

1
2
3
4
5
6
7
8
9
10
11
12
13
// 通过 Unit8Array 创建一个数组
const arrA = Uint8Array.from([0x61, 0x62, 0x63, 0x64])

const arrB = new Uint8Array(arrA.buffer, 0,3)

const buf = Buffer.from(arrB.buffer)

// abcd
console.log(buf.toString())

// or
const buff = Buffer.from([0x61, 0x62, 0x63, 0x64])
console.log(buff.toString())
buf.toJSON()
1
2
3
4
5
6
7
8
9
10
11
12
13
// 通过 Unit8Array 创建一个数组
const arrA = Uint8Array.from([0x61, 0x62, 0x63, 0x64])

const arrB = new Uint8Array(arrA.buffer, 0,3)

const buf = Buffer.from(arrB.buffer)

// { type: 'Buffer', data: [ 97, 98, 99, 100 ] }
console.log(buf.toJSON())

// or
const buff = Buffer.from([0x61, 0x62, 0x63, 0x64])
console.log(buff.toJSON())

buffer.compare(target[,target1,target…])

Id Name Info
0x2 buffer.compare(target[,target1,target..]) 比较两个缓冲区(buffer)对象是否相等,并返回 -1、0、1
0 与 target 相等返回 0
1 如果 target 的 size 不同以及 fill 相等,则返回 1
-1 如果 target 的 fill 不相等,则返回 -1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const buf1 = Buffer.alloc(10,1)
const buf2 = Buffer.alloc(10,1)

// 0
var com = Buffer.compare(buf1,buf2)
console.log(com)

const buf3 = Buffer.alloc(10)
const buf4 = Buffer.alloc(10,1)

// -1
var com1 = Buffer.compare(buf3,buf4)
console.log(com1)

const buf5 = Buffer.alloc(10,1)
const buf6 = Buffer.alloc(10,1)

// 1
var com2 = Buffer.compare(buf5,buf6)
console.log(com2)

buffer.concat()

1
2
3
4
5
6
7
8
9
10
const buf = Buffer.alloc(3)
const buf1 = Buffer.alloc(1)
const buf2 = Buffer.alloc(1)

var arr = [buf, buf1, buf2]

var con = Buffer.concat(arr)

// 5 <Buffer 00 00 00 00 00>
console.log(Buffer.byteLength(con), con)

buffer.entries()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const buf = Buffer.from('hello,world!')

/*
[ 0, 104 ]
[ 1, 101 ]
[ 2, 108 ]
[ 3, 108 ]
[ 4, 111 ]
[ 5, 44 ]
[ 6, 119 ]
[ 7, 111 ]
[ 8, 114 ]
[ 9, 108 ]
[ 10, 100 ]
[ 11, 33 ]
*/
for (var point of buf.entries()) {
console.log(point)
}

// 104
console.log(buf[0])

.buffer.entries() 与直接通过 buf[0] 这种逐一输出更加的方便和快捷。

buffer.fill

1
2
3
4
5
6
7
8
const buf = Buffer.alloc(5).fill('hello')

// hello
console.log(buf.toString())

// or
const buf2 = Buffer.alloc(5,'hello')
console.log(buf2.toString())

buffer.includes(values)

1
2
3
4
5

const buf = Buffer.from('This is Buffer')

// true false
console.log(buf.includes('is'), buf.includes('as'))

buf.slice(start[,end])

1
2
3
4
5
const buf = Buffer.from('abcd')
const sli = buf.slice(0, 2)

// ab
console.log(sli.toString())

buf.write(string[,offset,length,encoding])

1
2
3
4
const buf = Buffer.alloc(6);
const len = buf.write('buffer',0,6, 'utf8')

console.log(`byte: ${buf} length: ${len}`)

字符编码转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const buffer = Buffer.from('hello,world!', 'ascii')

// hello,world!
console.log(buffer.toString('ascii'))

/**
* 104 101 108 108
* h -> 104
* e -> 101
* l -> 108
* l -> 108
*/
console.log(buffer[0],buffer[1],buffer[2],buffer[3])

缓冲区是一个字节数据,因此可以像数组一样进行访问,除此它还支持数种编码的转换:

Id Name Info Type
1 uft8 (utf-8) 多字节的 Unicode 字符,许多网页和玩文档格式使用 UFT-8 也是 默认的字符编码(当 buffer 解码过程中如果 UTF-8 不是有效字符,将会以 unicode 替换字符 � 用于表示错误) 字符串
2 utf16le(utf-16le) 多字节编码的 Unicode 字符,与 utf8 不同的是字符串中每个字符都将使用 2个或4个 字节进行编码 字符串
3 latin1 (Latin-1) 即 ISO-8859-1 ,因此此编码仅支持 U+0000~U+00FF 的 Unicode 字符,每个字符都将使用单字节进行编码(一种一字节的字符串方式) 字符串
4 base64 一种基于 64 个可打印字符来表示二进制数据的方法,可打印的字母 a-z\A-Z 以及数字 0-9,此外还包含空白字符(空格、制表符或换行符)会被 buffer 忽略 二进制
5 base64url 一个对 base64 标准的修改,其目的是能将编码结果用于文件名或 URL 地址,当字符串通过 buffer 时,base64url 也将接受常规的 base64 编码转换。 二进制
6 hex(16 进制) 将每个字节转换为十六进制字符 二进制
7 ascii 仅用于 7 位数的 ASCII 数据,当通过 buffer 时,将会等效于 Lantin-1 旧字符
8 binary (Lation-1) Lation-1 的别名,通过此编码列出的所有编码都会在字符串和二进制之间转换 旧字符
9 ucs2(utf-16le) uft-16le 的别名,泛指 UTF-16 的一种变体,此编码不支持大于 U+FFFF 的字符 旧字符

可以通过使用 buffer.isEncoding 方法来进行判断 Buffer 是否支持该编码类型。

本文使用《江雪分析公开知识存储库知识共享许可证》进行发布